"""Customer Quality Scoring Service - MVP1 Implementation.

基于5个核心维度的客户质量评分算法：
1. 意向强度 (30分): 需求紧急度、跟进阶段
2. 财务能力 (25分): 预算合理性、需求类型匹配
3. 行为活跃度 (20分): 看房次数、最近互动时间
4. 需求明确度 (15分): 标签完整性、备注详细度
5. 来源质量 (10分): 渠道评分
"""

from datetime import datetime, timedelta
from typing import Optional

from sqlalchemy.orm import Session

from ..models.lead import Lead
from ..models.enums import DemandType, SourceChannel, LeadStage, QualityGrade
from ..models.visitor_sheet import VisitorSheet


class QualityScoringService:
    """客户质量评分服务."""

    # 渠道质量权重（基于转化率经验值）
    CHANNEL_SCORES = {
        SourceChannel.REFERRAL: 10,  # 转介绍（最优）
        SourceChannel.OFFLINE: 8,    # 线下
        SourceChannel.WALK_IN: 8,    # 到店
        SourceChannel.WECHAT: 7,     # 微信
        SourceChannel.PHONE: 6,      # 电话
        SourceChannel.DOUYIN: 5,     # 抖音
        SourceChannel.OTHER: 3,      # 其他
    }

    # 跟进阶段质量权重
    STAGE_SCORES = {
        LeadStage.VIEWING: 15,          # 看房中（最高意向）
        LeadStage.NEGOTIATING: 12,      # 协商中
        LeadStage.CONTACTED: 8,         # 已联系
        LeadStage.NEW: 5,               # 新客户
        LeadStage.CLOSED_WON: 0,        # 已成交（不再评分）
        LeadStage.CLOSED_LOST: 0,       # 已流失（不再评分）
    }

    def __init__(self, db: Session):
        """Initialize scoring service."""
        self.db = db

    def calculate_quality_score(self, lead: Lead) -> tuple[int, QualityGrade]:
        """
        计算客户质量分数和等级.

        Returns:
            (score, grade): 分数（0-100）和等级（S/A/B/C/D）
        """
        # 1. 意向强度 (30分)
        intention_score = self._score_intention(lead)

        # 2. 财务能力 (25分)
        financial_score = self._score_financial_capability(lead)

        # 3. 行为活跃度 (20分)
        behavior_score = self._score_behavior(lead)

        # 4. 需求明确度 (15分)
        clarity_score = self._score_clarity(lead)

        # 5. 来源质量 (10分)
        source_score = self._score_source(lead)

        # 总分
        total_score = (
            intention_score +
            financial_score +
            behavior_score +
            clarity_score +
            source_score
        )

        # 确保分数在0-100之间
        total_score = max(0, min(100, int(total_score)))

        # 计算等级
        grade = self._calculate_grade(total_score)

        return total_score, grade

    def _score_intention(self, lead: Lead) -> float:
        """评分：意向强度 (30分)."""
        score = 0.0

        # 跟进阶段得分 (15分)
        score += self.STAGE_SCORES.get(lead.stage, 0)

        # 额外意向评估 (15分)
        # 检查是否有额外的明确意向
        if lead.intentions and len(lead.intentions) > 0:
            # 有额外意向，说明需求多样化
            score += 10

            # 如果有高意向的额外需求
            high_intention_count = sum(
                1 for intention in lead.intentions
                if hasattr(intention, 'intention_level') and
                str(intention.intention_level).lower() in ['high', 'medium']
            )
            if high_intention_count > 0:
                score += 5

        # 如果有标签，说明需求有特点
        if lead.tag_names and len(lead.tag_names.strip()) > 0:
            score += 5

        return score

    def _score_financial_capability(self, lead: Lead) -> float:
        """评分：财务能力 (25分)."""
        score = 0.0

        # 是否有预算 (10分)
        if lead.budget_range and len(lead.budget_range.strip()) > 0:
            score += 10

            # 预算合理性检查 (15分)
            if self._validate_budget_reasonability(lead.demand_type, lead.budget_range):
                score += 15
            else:
                # 预算不合理，只给5分
                score += 5

        return score

    def _score_behavior(self, lead: Lead) -> float:
        """评分：行为活跃度 (20分)."""
        score = 0.0

        # 查询看房次数
        viewing_count = (
            self.db.query(VisitorSheet)
            .filter(VisitorSheet.lead_id == lead.id)
            .filter(VisitorSheet.is_deleted == False)
            .count()
        )

        # 看房次数得分 (10分)
        if viewing_count >= 3:
            score += 10
        elif viewing_count == 2:
            score += 7
        elif viewing_count == 1:
            score += 4

        # 最近活跃度得分 (10分)
        # 检查更新时间
        if hasattr(lead, 'updated_at') and lead.updated_at:
            days_since_update = (datetime.now() - lead.updated_at).days

            if days_since_update <= 3:  # 3天内活跃
                score += 10
            elif days_since_update <= 7:  # 7天内活跃
                score += 7
            elif days_since_update <= 14:  # 14天内活跃
                score += 4
            elif days_since_update <= 30:  # 30天内活跃
                score += 2

        return score

    def _score_clarity(self, lead: Lead) -> float:
        """评分：需求明确度 (15分)."""
        score = 0.0

        # 标签完整性 (8分)
        if lead.tag_names and len(lead.tag_names.strip()) > 0:
            tag_count = len([t for t in lead.tag_names.split(',') if t.strip()])

            if tag_count >= 3:
                score += 8
            elif tag_count == 2:
                score += 5
            elif tag_count == 1:
                score += 3

        # 备注详细度 (7分)
        if lead.notes and len(lead.notes.strip()) > 0:
            notes_length = len(lead.notes.strip())

            if notes_length >= 50:  # 详细备注
                score += 7
            elif notes_length >= 20:  # 中等备注
                score += 4
            elif notes_length >= 5:  # 简短备注
                score += 2

        return score

    def _score_source(self, lead: Lead) -> float:
        """评分：来源质量 (10分)."""
        return self.CHANNEL_SCORES.get(lead.source_channel, 3)

    def _validate_budget_reasonability(
        self,
        demand_type: Optional[DemandType],
        budget_range: Optional[str]
    ) -> bool:
        """验证预算合理性."""
        if not budget_range or not demand_type:
            return False

        try:
            import re
            numbers = re.findall(r'\d+', budget_range)
            if not numbers:
                return False

            min_budget = int(numbers[0])
            max_budget = int(numbers[-1]) if len(numbers) > 1 else min_budget

            # 租房场景：预算应该在 500-50000 元/月
            if demand_type in [DemandType.RENT_WHOLE, DemandType.RENT_SHARED, DemandType.RENT_SHORT]:
                if min_budget < 100 or max_budget > 100000:
                    return False
                if min_budget > 50000:
                    return False

            # 买房场景：预算应该在 50-10000 万元
            elif demand_type == DemandType.BUY:
                if min_budget < 10 or max_budget > 50000:
                    return False

            # 卖房场景：预算即为期望价格
            elif demand_type == DemandType.SELL:
                if min_budget < 50 or max_budget > 50000:
                    return False

            # 最小值不能大于最大值
            if min_budget > max_budget:
                return False

            return True
        except (ValueError, IndexError):
            return False

    def _calculate_grade(self, score: int) -> QualityGrade:
        """根据分数计算等级."""
        if score >= 90:
            return QualityGrade.S
        elif score >= 80:
            return QualityGrade.A
        elif score >= 70:
            return QualityGrade.B
        elif score >= 60:
            return QualityGrade.C
        else:
            return QualityGrade.D

    def update_lead_quality(self, lead: Lead) -> Lead:
        """
        更新客户质量评分.

        Args:
            lead: 客户对象

        Returns:
            更新后的客户对象
        """
        score, grade = self.calculate_quality_score(lead)

        lead.quality_score = score
        lead.quality_grade = grade
        lead.quality_updated_at = datetime.now()

        self.db.add(lead)
        self.db.commit()
        self.db.refresh(lead)

        return lead

    def batch_update_quality_scores(
        self,
        limit: Optional[int] = None
    ) -> int:
        """
        批量更新所有客户的质量评分.

        Args:
            limit: 限制更新数量（用于大规模数据）

        Returns:
            更新的客户数量
        """
        query = (
            self.db.query(Lead)
            .filter(Lead.is_deleted == False)
            .filter(Lead.stage.notin_([LeadStage.CLOSED_WON, LeadStage.CLOSED_LOST]))
        )

        if limit:
            query = query.limit(limit)

        leads = query.all()
        updated_count = 0

        for lead in leads:
            try:
                self.update_lead_quality(lead)
                updated_count += 1
            except Exception as e:
                print(f"Failed to update quality for lead {lead.id}: {e}")
                continue

        return updated_count
